package cn.stylefeng.guns.modular.stock.service.impl;

import cn.hutool.http.HttpUtil;
import cn.stylefeng.guns.base.pojo.page.LayuiPageFactory;
import cn.stylefeng.guns.base.pojo.page.LayuiPageInfo;
import cn.stylefeng.guns.base.util.GunsTheadPool;
import cn.stylefeng.guns.modular.stock.entity.StockStrategy;
import cn.stylefeng.guns.modular.stock.mapper.StockStrategyMapper;
import cn.stylefeng.guns.modular.stock.model.params.StockStrategyParam;
import cn.stylefeng.guns.modular.stock.model.result.StockStrategyResult;
import cn.stylefeng.guns.modular.stock.service.StockStrategyService;
import cn.stylefeng.roses.core.util.ToolUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.tuyang.beanutils.BeanCopyUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.converter.json.GsonBuilderUtils;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xzan
 * @since 2020-03-15
 */
@Service
public class StockStrategyServiceImpl extends ServiceImpl<StockStrategyMapper, StockStrategy> implements StockStrategyService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private Gson gson;

    private final static String sinaStockUrl = "http://hq.sinajs.cn/list=";


    @Override
    public void add(StockStrategyParam param) {
        StockStrategy entity = getEntity(param);
        if (Objects.isNull(entity.getGmtCreate())) {
            entity.setGmtCreate(new Date());
        }
        if (Objects.isNull(entity.getGmtModified())) {
            entity.setGmtModified(new Date());
        }
        entity.setStatus(1);
        this.save(entity);
    }

    @Override
    public void delete(StockStrategyParam param) {
        this.removeById(getKey(param));
    }

    @Override
    public void sellDirectly(StockStrategyParam param) {
        StockStrategy stockStrategy = this.getById(getKey(param));
        stockStrategy.setEventType(5);
        float currentPrice = getCurrentPrice(stockStrategy.getCode());
        stockStrategy.setTakeProfitPrice(currentPrice);
        redisTemplate.convertAndSend("strategy_event", toUnderlineJSONString(stockStrategy));
    }

    /**
     * buy direct
     *
     * @param param
     */
    @Override
    public void buyDirectly(StockStrategyParam param) {
        StockStrategy stockStrategy = this.getById(getKey(param));
        stockStrategy.setEventType(1);
        float currentPrice = getCurrentPrice(stockStrategy.getCode());
        stockStrategy.setTakeProfitPrice(currentPrice);
        redisTemplate.convertAndSend("strategy_event", toUnderlineJSONString(stockStrategy));
    }

    public static String toUnderlineJSONString(Object object) {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        try {
            String reqJson = mapper.writeValueAsString(object);
            return reqJson;
        } catch (Exception e) {
            throw new RuntimeException("object to under line exception");

        }

    }

    @Override
    public void update(StockStrategyParam param) {
        StockStrategy oldEntity = getOldEntity(param);
        StockStrategy newEntity = getEntity(param);
        ToolUtil.copyProperties(newEntity, oldEntity);
        this.updateById(newEntity);
        //send message to notify the exchange program
        GunsTheadPool.pool.execute(new Runnable() {
            @Override
            public void run() {
                redisTemplate.convertAndSend("strategy_modify_event", gson.toJson(newEntity));
            }
        });

    }

    @Override
    public StockStrategyResult findBySpec(StockStrategyParam param) {
        return null;
    }

    @Override
    public List<StockStrategyResult> findListBySpec(StockStrategyParam param) {
        return null;
    }

    @Override
    public LayuiPageInfo findPageBySpec(StockStrategyParam param) {
        Page pageContext = getPageContext();
        IPage page = this.baseMapper.customPageList(pageContext, param);
        String profitRatio = this.baseMapper.totalProfitRatio();
        LayuiPageInfo layuiPageInfo = LayuiPageFactory.createPageInfo(page);
        HashMap others = new HashMap();
        others.put("totalProfitRatio", profitRatio);
        layuiPageInfo.setOthers(others);
        return layuiPageInfo;
    }

    private Serializable getKey(StockStrategyParam param) {
        return param.getId();
    }

    private Page getPageContext() {
        return LayuiPageFactory.defaultPage();
    }

    private StockStrategy getOldEntity(StockStrategyParam param) {
        return this.getById(getKey(param));
    }

    private StockStrategy getEntity(StockStrategyParam param) {
        StockStrategy entity = new StockStrategy();
        BeanCopyUtils.copyBean(param, entity);
        return entity;
    }

    private float getCurrentPrice(String code) {
        if (code.startsWith("00")) {
            code = "sz" + code;
        }
        if (code.startsWith("60")) {
            code = "sh" + code;
        }
        if (code.startsWith("300")) {
            code = "sz" + code;
        }
        String content = HttpUtil.get(sinaStockUrl + code);
        if (StringUtils.isNotBlank(content)) {
            String[] splitStrings = content.split("=");
            if (!Objects.isNull(splitStrings) && splitStrings.length == 2) {
                String stockInfo = splitStrings[1];
                stockInfo = stockInfo.replace("\"", "");
                System.out.println(stockInfo);
                String[] stockCompleteInfo = stockInfo.split(",");
                String currentPrice = stockCompleteInfo[3];
                return Float.parseFloat(currentPrice);
            }
        }
        return 0;
    }

}
